#import "AliyunVodUploadPlugin.h"
#import <VODUpload/VODUploadClient.h>
#import "model/InitModel.m"
#import "utils/Paser.m"
NSObject<FlutterPluginRegistrar> *_registrar;
FlutterEventChannel *_eventChannel;

VODUploadClient *uploader;
NSMutableArray *percentList;
struct StsInitModel stsInitModel;
struct AuthInitModel authInitModel;

@implementation AliyunVodUploadPlugin

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
    FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"aliyun_vod_upload" binaryMessenger:[registrar messenger]];
    AliyunVodUploadPlugin *instance = [[AliyunVodUploadPlugin alloc] initWithRegistrar:registrar];
    [registrar addMethodCallDelegate:instance channel:channel];
    _eventChannel = [FlutterEventChannel eventChannelWithName:@"aliyun_vod_upload/event" binaryMessenger:[_registrar messenger]];
    [_eventChannel setStreamHandler:instance];
}

- (instancetype)initWithRegistrar:
    (NSObject<FlutterPluginRegistrar> *)registrar {
  self = [super init];
  if (self) {
      percentList = [[NSMutableArray alloc] init];
      _registrar = registrar;
  }
  return self;
}

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {

  if ([@"getPlatformVersion" isEqualToString:call.method]) {
    result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
  } else if([@"stsInit" isEqualToString:call.method]) {
//      [self stsInit: call result: result];
      result([NSNumber numberWithBool: NO]);
  } else if([@"authInit" isEqualToString:call.method]) {
      [self authInit: call result: result];
  } else if ([@"addFile" isEqualToString:call.method]) {
      [self addFile: call result: result];
  } else if([@"startUpload" isEqualToString:call.method]) {
      NSLog(@"开始上传");
      bool OK = [uploader start];
      result([NSNumber numberWithBool: OK]);
  } else if([@"deleteFile" isEqualToString:call.method]) {
      [self deleteFile: call result: result];
  } else if([@"cancelFile" isEqualToString:call.method]) {
      [self cancelFile: call result: result];
  } else if([@"resumeFile" isEqualToString:call.method]) {
      [self resumeFile: call result: result];
  } else if([@"getList" isEqualToString:call.method]) {
      [self getList: call result: result];
  } else if([@"clearList" isEqualToString:call.method]) {
      [self clearList: call result: result];
  } else if([@"stopUpload" isEqualToString:call.method]) {
      [self stopUpload: call result: result];
  } else if([@"pauseUpload" isEqualToString:call.method]) {
      [self pauseUpload: call result: result];
  } else if([@"resumeUpload" isEqualToString:call.method]) {
      [self resumeUpload: call result: result];
  } else if([@"resumeWithToken" isEqualToString:call.method]) {
      [self resumeWithToken: call result: result];
  } else {
    result(FlutterMethodNotImplemented);
  }
}

- (void)stsInit:(FlutterMethodCall*)call result:(FlutterResult)result {
    stsInitModel.key = call.arguments[@"key"];
    stsInitModel.expireTime = call.arguments[@"expireTime"];
    stsInitModel.keySecret = call.arguments[@"keySecret"];
    stsInitModel.secretToken = call.arguments[@"secretToken"];
    //创建VODUploadClient对象
    uploader = [VODUploadClient new];
    //setup callback
    // 完成回调
    OnUploadFinishedListener FinishCallbackFunc = ^(UploadFileInfo* fileInfo,  VodUploadResult* result){
        NSLog(@"完成回调 videoid:%@, imageurl:%@", result.videoId, result.imageUrl);
        NSDictionary *dic = @{@"event": @"OnUploadFinishedListener", @"uploadFileInfo": [Paser getObjectData: fileInfo], @"vodUploadResult": [Paser getObjectData: result]};
        self.eventSink([Paser getJson: dic]);
    };
    // 失败回调
    OnUploadFailedListener FailedCallbackFunc = ^(UploadFileInfo* fileInfo, NSString *code, NSString* message){
        NSLog(@"失败回调 code = %@, error message = %@", code, message);
        NSDictionary *dic = @{@"event": @"OnUploadFailedListener", @"uploadFileInfo": [Paser getObjectData: fileInfo], @"code": code, @"message": message};
        self.eventSink([Paser getJson: dic]);
    };
    // 进度回调
    OnUploadProgressListener ProgressCallbackFunc = ^(UploadFileInfo* fileInfo, long uploadedSize, long totalSize) {
        NSLog(@"进度回调 : %li, totalSize : %li", uploadedSize, totalSize);
        UploadFileInfo* info;
        int i = 0;
        for(; i<[[uploader listFiles] count]; i++) {
            info = [[uploader listFiles] objectAtIndex:i];
            if (info == fileInfo) {
                break;
            }
        }
        if (nil == info) {
            return;
        }
        
        [percentList setObject:[NSString stringWithFormat:@"%ld", uploadedSize*100/totalSize] atIndexedSubscript:i];
        NSDictionary *dic = @{@"event": @"OnUploadProgressListener", @"uploadFileInfo": [Paser getObjectData: fileInfo], @"uploadedSize": [NSNumber numberWithLong: uploadedSize], @"totalSize": [NSNumber numberWithLong: totalSize]};
        self.eventSink([Paser getJson: dic]);
    };
    // token过期回调
    OnUploadTokenExpiredListener TokenExpiredCallbackFunc = ^{
        NSLog(@"token过期回调");
        //token过期，设置新的STS，继续上传
        NSDictionary *dic = @{@"event": @"OnUploadTokenExpiredListener"};
        self.eventSink([Paser getJson: dic]);
    };
    // 重试开始回调
    OnUploadRertyListener RetryCallbackFunc = ^{
        NSLog(@"重试开始回调");
        NSDictionary *dic = @{@"event": @"OnUploadRertyListener"};
        self.eventSink([Paser getJson: dic]);
    };
    // 重试结束回调
    OnUploadRertyResumeListener RetryResumeCallbackFunc = ^{
        NSLog(@"重试结束回调");
        NSDictionary *dic = @{@"event": @"OnUploadRertyResumeListener"};
        self.eventSink([Paser getJson: dic]);
    };
    // 开始上传回调
    OnUploadStartedListener UploadStartedCallbackFunc = ^(UploadFileInfo* fileInfo) {
        NSLog(@"开始上传回调");
        NSDictionary *dic = @{@"event": @"OnUploadStartedListener"};
        self.eventSink([Paser getJson: dic]);
    };
    //init
    VODUploadListener *listener = [[VODUploadListener alloc] init];
    listener.finish = FinishCallbackFunc;
    listener.failure = FailedCallbackFunc;
    listener.progress = ProgressCallbackFunc;
    listener.expire = TokenExpiredCallbackFunc;
    listener.retry = RetryCallbackFunc;
    listener.retryResume = RetryResumeCallbackFunc;
    listener.started = UploadStartedCallbackFunc;
    //set STS and listener
    [uploader setKeyId: stsInitModel.key accessKeySecret: stsInitModel.keySecret secretToken: stsInitModel.secretToken expireTime: stsInitModel.expireTime listener:listener];
    NSLog(@"初始化完成");
    result(@"iOS Success");
}

- (void)authInit:(FlutterMethodCall*)call result:(FlutterResult)result {
    
    authInitModel.address = call.arguments[@"uploadAddress"];
    authInitModel.auth = call.arguments[@"uploadAuth"];
    //创建VODUploadClient对象
    uploader = [VODUploadClient new];
    //setup callback
    // 完成回调
    OnUploadFinishedListener FinishCallbackFunc = ^(UploadFileInfo* fileInfo,  VodUploadResult* result){
        NSLog(@"完成回调 videoid:%@, imageurl:%@", result.videoId, result.imageUrl);
        
        NSDictionary *dic = @{@"event": @"OnUploadFinishedListener", @"uploadFileInfo": [Paser getObjectData: fileInfo], @"vodUploadResult": [Paser getObjectData: result]};
        self.eventSink([Paser getJson: dic]);
    };
    // 失败回调
    OnUploadFailedListener FailedCallbackFunc = ^(UploadFileInfo* fileInfo, NSString *code, NSString* message){
        NSLog(@"失败回调 code = %@, error message = %@", code, message);
        NSDictionary *dic = @{@"event": @"OnUploadFailedListener", @"uploadFileInfo": [Paser getObjectData: fileInfo], @"code": code, @"message": message};
        self.eventSink([Paser getJson: dic]);
    };
    // 进度回调
    OnUploadProgressListener ProgressCallbackFunc = ^(UploadFileInfo* fileInfo, long uploadedSize, long totalSize) {
        NSLog(@"进度回调 : %li, totalSize : %li", uploadedSize, totalSize);
        NSDictionary *dic = @{@"event": @"OnUploadProgressListener", @"uploadFileInfo": [Paser getObjectData: fileInfo], @"uploadedSize": [NSNumber numberWithLong: uploadedSize], @"totalSize": [NSNumber numberWithLong: totalSize]};
        self.eventSink([Paser getJson: dic]);
    };
    // token过期回调
    OnUploadTokenExpiredListener TokenExpiredCallbackFunc = ^{
        NSLog(@"token过期回调");
        //token过期，设置新的上传凭证，继续上传
//        [uploader resumeWithAuth: authInitModel.auth];
        
    };
    // 重试开始回调
    OnUploadRertyListener RetryCallbackFunc = ^{
        NSLog(@"重试开始回调");
//        NSDictionary *dic = @{@"event": @"OnUploadRertyListener"};
//        self.eventSink([Paser getJson: dic]);
    };
    // 重试结束回调
    OnUploadRertyResumeListener RetryResumeCallbackFunc = ^{
        NSLog(@"重试结束回调");
//        NSDictionary *dic = @{@"event": @"OnUploadRertyResumeListener"};
//        self.eventSink([Paser getJson: dic]);
    };
    // 开始上传回调
    OnUploadStartedListener UploadStartedCallbackFunc = ^(UploadFileInfo* fileInfo) {
        NSLog(@"开始上传回调");
        NSLog(@"是否是流文件：%s, 文件路径：%@, oss的endpoint：%@, oss的bucket：%@, oss的对象：%@， vod上传状态：%ld", fileInfo.isStreamFile ? "YES" : "NO", fileInfo.filePath, fileInfo.endpoint, fileInfo.bucket, fileInfo.object, (long)fileInfo.state);
        bool results = [uploader setUploadAuthAndAddress:fileInfo uploadAuth: authInitModel.auth uploadAddress: authInitModel.address];
        NSLog(@"上传时存入结果：%s", results ? "YES":"NO");
        NSDictionary *dic = @{@"event": @"OnUploadStartedListener", @"uploadFileInfo": [Paser getObjectData: fileInfo]};
        self.eventSink([Paser getJson: dic]);
        
    };
    //init
    VODUploadListener *listener = [[VODUploadListener alloc] init];
    listener.finish = FinishCallbackFunc;
    listener.failure = FailedCallbackFunc;
    listener.progress = ProgressCallbackFunc;
    listener.expire = TokenExpiredCallbackFunc;
    listener.retry = RetryCallbackFunc;
    listener.retryResume = RetryResumeCallbackFunc;
    listener.started = UploadStartedCallbackFunc;
    bool results = [uploader setListener:listener];
    NSLog(@"初始化完成");
    result(@"iOS Success");
}

- (void)stopUpload:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSLog(@"停止上传");
    [uploader stop];
//    NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:0];
    result(@"iOS Success");
}

- (void)pauseUpload:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSLog(@"暂停上传");
    [uploader pause];
//    NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:0];
    result(@"iOS Success");
}

- (void)resumeUpload:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSLog(@"回复上传");
    [uploader resume];
//    NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:0];
    result(@"iOS Success");
}

- (void)resumeWithToken:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSLog(@"刷新token");
    [uploader resumeWithToken: call.arguments[@"keyId"] accessKeySecret: call.arguments[@"keySecret"] secretToken: call.arguments[@"token"] expireTime: call.arguments[@"expireTime"]];
    result(@"iOS Success");
}

- (void)addFile:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSLog(@"添加文件");
    NSString *filePath = call.arguments[@"filePath"];
    VodInfo *vodInfo = [[VodInfo alloc] init];
    vodInfo.title = call.arguments[@"vodInfoModel"][@"title"];
    vodInfo.desc = call.arguments[@"vodInfoModel"][@"desc"];
    vodInfo.cateId = call.arguments[@"vodInfoModel"][@"cateId"];
    vodInfo.coverUrl = call.arguments[@"vodInfoModel"][@"coverUrl"];
    vodInfo.tags = call.arguments[@"vodInfoModel"][@"tags"];
    bool OK = [uploader addFile: filePath vodInfo:vodInfo];
    result([NSNumber numberWithBool: OK]);
}

- (void)deleteFile:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSLog(@"删除文件");
    NSMutableArray<UploadFileInfo *> *list = [uploader listFiles];
    if ([list count] <= 0) {
        return;
    }
    NSInteger index = [uploader listFiles].count-1;
    NSString *fileName = [list objectAtIndex:index].filePath;
    [uploader deleteFile:(int)index];
    NSLog(@"删除文件: %@", fileName);
    if (percentList.count > 0) {
        [percentList removeObjectAtIndex:percentList.count - 1];
    }
    
//    NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:0];
    result(@"iOS Success");
}

- (void)cancelFile:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSLog(@"取消文件");
    NSMutableArray<UploadFileInfo *> *list = [uploader listFiles];
    if ([list count] <= 0) {
        return;
    }
    
    NSInteger index = [uploader listFiles].count-1;
    NSString *fileName = [list objectAtIndex:index].filePath;
    [uploader cancelFile:(int)index];
    NSLog(@"取消文件: %@", fileName);
    
//    NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:0];
    result(@"iOS Success");
}

- (void)resumeFile:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSLog(@"恢复文件.");
    NSMutableArray<UploadFileInfo *> *list = [uploader listFiles];
    if ([list count] <= 0) {
        return;
    }
    
    NSInteger index = [uploader listFiles].count-1;
    NSString *fileName = [list objectAtIndex:index].filePath;
    [uploader resumeFile:(int)index];
    NSLog(@"恢复文件: %@", fileName);
//    NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:0];
    result(@"iOS Success");
    
}

- (void)getList:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSLog(@"获取上传列表");
    [uploader listFiles];
    result(@"iOS Success");
}

- (void)clearList:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSLog(@"清空上传列表");
    [uploader clearFiles];
    [percentList removeAllObjects];
    
//    NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:0];
    result(@"iOS Success");
    
}

#pragma mark - FlutterStreamHandler
- (FlutterError * _Nullable)onCancelWithArguments:(id _Nullable)arguments {
    self.eventSink=nil;
    return nil;
}

- (FlutterError * _Nullable)onListenWithArguments:(id _Nullable)arguments eventSink:(nonnull FlutterEventSink)events {
    self.eventSink=events;
    return nil;
}

// 添加事件
-(void) addEvent:(NSObject *) event{
    if(self.eventSink!=nil){
        self.eventSink(event);
    }
}

@end
